package edu.cmu.vlis.wassup.db;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import org.mybeans.editor.BeanEditor;
import org.mybeans.factory.BeanFactory;
import org.mybeans.factory.BeanTable;
import org.mybeans.factory.MatchArg;
import org.mybeans.factory.RollbackException;
import org.mybeans.factory.Transaction;

public class Announcement_User_Dao {
	// Private table used to store user's address information
	private BeanTable<Announcement_User> messageTable;
	private BeanFactory<Announcement_User> messageFactory;
	
	private static void loadProperties(){
        Properties props = new Properties();
        try {
            props.load(new FileInputStream("src/properties"));
            System.getProperties().putAll(props);
            
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

	/** Constructor of Editor
	 * The default is used to store records in MYSQL database
	 * without JDBC connection information 
	 * 
	 */
	public Announcement_User_Dao() {
			//loadProperties();
			BeanTable.useJDBC("com.mysql.jdbc.Driver", System.getProperty("org.mybeans.factory.jdbcURL")+"?user=root&password=wassup");
			// initialize table and bean factory
			AnnouncementDao ad = new AnnouncementDao();
			UserDao ud = new UserDao();
			messageTable = BeanTable.getInstance(Announcement_User.class,"Announcement_User", ad.getFactory(), ud.getFactory()); // Get profile table
			createTable();
	}
	
	/** Constructor of Editor
	 * The default is used to store records in MYSQL database
	 * 
	 * @param URL
	 */
	public Announcement_User_Dao(String URL) {
			// TODO Auto-generated method stub
			// Records are stored in MYSQL
			// clear the system property first
			System.clearProperty("org.mybeans.factory.csvDirectory");
			// Link to jdbc driver through mysql
			System.setProperty("org.mybeans.factory.jdbcDriver","com.mysql.jdbc.Driver");
			System.setProperty("org.mybeans.factory.jdbcURL","jdbc:mysql://"+URL+"/wassup");
	
			// Indicate username/password to the mysql database
			System.setProperty("org.mybeans.factory.user", "root" );
			System.setProperty("org.mybeans.factory.password", "wassup");
		
			// initialize table and bean factory
			AnnouncementDao ad = new AnnouncementDao();
			UserDao ud = new UserDao();
			messageTable = BeanTable.getInstance(Announcement_User.class,"Announcement_User", ad.getFactory(), ud.getFactory()); // Get address table
			createTable();
	}
	
	/** Create an Profile beanTable 
	 * 1) if it already exists, keep the old one.
	 * 2) if it does not exist, create a new one.
	 * 
	 */
	public void createTable() {
		// Check whether the table has existed
		// If it is the case, delete the old table
		if (!messageTable.exists()) 
			// Create a new table
			//messageTable.create("announcement_profile_id"); // Indicate primary key
			messageTable.create("announcement_id", "receiver_id");
		
		// get the bean factory to the table
		messageFactory = messageTable.getFactory();
	}
	
	// Call for bean editor
	public void createEditor() {
		BeanEditor<Announcement_User> editor = BeanEditor.getInstance(messageFactory);
		editor.start();
	}
	
	/**
	 * To check whether the given user and announcement mapping exists
	 * @param announcement_id
	 * @param receiver_id
	 * @return
	 * @throws RollbackException 
	 */
	public String validate(Announcement announcement_id, User receiver_id) throws RollbackException {
		Announcement_User message = messageFactory.lookup(announcement_id, receiver_id);
		if (message==null) return null;
		return "Message Found";
	}

	/** Insert a new tuple of Announcement_user into the beanTable
	 * Returns error message if creation fails.
	 * Otherwise return a null upon success.
	 * 
	 * @param announcement_id
	 * @param receiver_id
	 * @return
	 * @throws RollbackException
	 */
	public long insert(Announcement announcement, User receiver) throws RollbackException 
	{
		if (!Transaction.isActive())	// If the former transaction does not end normally
			Transaction.begin();	// Begin a new transaction
		
		if (validate(announcement, receiver)!=null)	// Check whether the user has been inserted before
			throw new RollbackException("The tuple has already been stored!");
		
		//Announcement_User message = messageFactory.create(announcement_profile_id);
		messageFactory.create(announcement, receiver);
		
		Transaction.commit();
		return 0;
		
	}
	
	/** Lookup whether a typical Announcement_User exists in the table
	 * Return Not Found if the addresss information is missing
	 * Otherwise return detailed information about address of a user
	 * 
	 * @param announcement_id
	 * @param receiver_id
	 * @return
	 * @throws RollbackException
	 */
	public Announcement_User lookup(Announcement announcement_id, User receiver_id) throws RollbackException {
		Announcement_User message = messageFactory.lookup(announcement_id, receiver_id);
		// Looking up using primary key
		String result = "";
		if (message==null) {
			throw new RollbackException("The tuple is not found!");
		} 
		else {
			result+="SELECT: Message Id="+"; Announcement_id="+message.getAnnouncement_id()+
				"; ReceiverId="+message.getReceiver_id();
			result+=" \nin " + messageFactory.getBeanCount()+" results.";
		}
		System.out.println(result);
		
		return message;
	}
	
	
	/**
	 *  Delete a tuple with primary key as the composite key with Announcement_id and User_id from User_Announcement table
	 * @param announcement_id
	 * @param receiver_id
	 * @return
	 * @throws RollbackException
	 */
	// return null if no tuple is affected
	public Announcement_User delete(Announcement announcement_id, User receiver_id) throws RollbackException {
		Announcement_User message = messageFactory.lookup(announcement_id, receiver_id);
		// Looking up using primary key
		String result = "";
		if (message==null) {
			throw new RollbackException("The tuple is not found!");
		} 
		else {
			result+="DELETE: Message Id="+"; Announcement_id="+message.getAnnouncement_id()+
				"; ReceiverId="+message.getReceiver_id();
			result+=" \nin " + messageFactory.getBeanCount()+" results.";
			
			if (!Transaction.isActive())	// If the former transaction does not end normally
				Transaction.begin();	// Begin a new transaction
			
			messageFactory.delete(announcement_id, receiver_id);
			
			Transaction.commit();
		}
		System.out.println(result);
		return message;
	}
	
	/**
	 * Get all announcements send to a certain user
	 * @param u
	 * @return
	 * @throws RollbackException
	 */
	public Announcement[] getAnnouncementFromUserId(User u) throws RollbackException {
		Announcement_User[] au = null;

		au = messageFactory.match(MatchArg.equals("receiver_id",u));
		Announcement[] as = new Announcement[au.length];
		
		if (au.length>=1) {
			for (int i = 0; i<au.length; i++) {
//				as.add(au[i].getAnnouncement_id());
				as[i] = au[i].getAnnouncement_id();
			}
		}
		return as;
	}
	
	/**
	 * Get all the messages whose receiver is a certain user
	 * @param u
	 * @return
	 * @throws RollbackException
	 */
	public Announcement_User[] getMessageFromUser(User u) throws RollbackException {
		Announcement_User[] au = null;
		au = messageFactory.match(MatchArg.equals("receiver_id",u));
		return au;
	}
	
	/**
	 * Get all the messages about a certain announcement
	 * @param a
	 * @return
	 * @throws RollbackException
	 */
	public Announcement_User[] getMessageFromAnnouncement(Announcement a) throws RollbackException {
		Announcement_User[] au = null;
		au = messageFactory.match(MatchArg.equals("announcement_id",a));
		return au;
	}
	
	public static void main(String[] args) throws RollbackException {
		loadProperties();
		Announcement_User_Dao edit = new Announcement_User_Dao();
		AnnouncementDao ad = new AnnouncementDao();
		UserDao ud = new UserDao();
		
		Announcement a = ad.lookup("1");
		User u = ud.lookup("jassica.jiafei@gmail.com");
		edit.insert(a, u);
		Announcement[] as = edit.getAnnouncementFromUserId(u);
		for (int i = 0; i<as.length; i++) {
			Announcement at = as[i];
			System.out.println("Event is: "+at.getDescription());
		}
		
		//edit.delete(a, u);
	}
}
